package jmine.tec.report.impl;

import java.io.Serializable;

import jmine.tec.report.api.RendererParameters;
import jmine.tec.report.api.Report;
import jmine.tec.report.api.ReportElement;
import jmine.tec.report.api.ReportTextBox;
import jmine.tec.report.api.table.ReportCell;
import jmine.tec.report.impl.table.ReportCellImpl;
import jmine.tec.report.impl.table.ReportElementNewPage;
import jmine.tec.report.impl.table.ReportTableBuilder;
import jmine.tec.report.impl.table.ReportTableInfoRowBuilder;
import jmine.tec.utils.UnmodifiableTuple;
import bancosys.tec.utils.date.Date;
import bancosys.tec.utils.date.DateUtils;
import bancosys.tec.utils.date.Timestamp;

/**
 * Builder de relatórios
 * 
 * @author lundberg
 */
public class ReportBuilder implements Serializable {

    public static final String REPORT_FOOTER_TEXT = "reportFooterText";

    public static final String TYPE_REPORT_HEADER = "reportHeader";

    public static final String TYPE_REPORT_FOOTER = "reportFooter";

    private Report report;

    /**
     * Construtor.
     * 
     * @param report {@link Report}
     */
    public ReportBuilder(Report report) {
        this.report = report;
    }

    /**
     * Construtor
     * 
     * @param title title
     * @param fileName fileName
     */
    public ReportBuilder(String title, String fileName) {
        this.report = new ReportImpl();
        this.report.getHeader().setTitle(title);
        this.report.getHeader().setFileName(fileName);
    }

    /**
     * Cria um novo builder de tabelas.
     * 
     * @param <V> tipo de elemento da tabela
     * @param valueClass valueClass
     * @param id id
     * @return ReportTableBuilder
     */
    public <V> ReportTableBuilder<V> createTableBuilder(Class<V> valueClass, String id) {
        return new ReportTableBuilder<V>(this, valueClass, id);
    }

    /**
     * Cria um novo builder de um tipo de tabela que recebe as linhas ao inves de colunas
     * 
     * @param <V> tipo de elemento da tabela
     * @param valueClass valueClass
     * @param id id
     * @return ReportTableInfoRowBuilder
     */
    public <V> ReportTableInfoRowBuilder<V> createReportTableInfoRowBuilder(Class<V> valueClass, String id) {
        return new ReportTableInfoRowBuilder<V>(this, valueClass, id);
    }

    /**
     * Adiciona um novo elemento ao relatório
     * 
     * @param element element
     */
    public void addElement(ReportElement element) {
        this.report.addElement(element);
    }

    /**
     * adiciona o new Page caso seja chamdo pelo usuario
     */
    public void addNewPageElement() {
        this.report.addElement(new ReportElementNewPage("newPage"));
    }

    /**
     * Adiciona um novo parâmetro de rodape ao relatório.
     * 
     * @param id id
     * @param label label
     * @param value value
     */
    public void addFooterStringParameter(String id, String label, String value) {
        ReportCell parameter = new ReportCellImpl(new UnmodifiableTuple<String, String>(label, value));
        parameter.setRendererType(TYPE_REPORT_FOOTER);
        this.report.getFooter().addParameter(parameter);
    }

    /**
     * Adiciona um novo parâmetro de cabeçalho ao relatório.
     * 
     * @param id id
     * @param label label
     * @param value value
     */
    public void addHeaderStringParameter(String id, String label, String value) {
        ReportCell parameter = new ReportCellImpl(new UnmodifiableTuple<String, String>(label, value));
        parameter.setRendererType(TYPE_REPORT_HEADER);
        this.report.getHeader().addParameter(parameter);
    }

    /**
     * Adiciona um novo parâmetro de cabeçalho ao relatório.
     * 
     * @param id id
     * @param label label
     * @param value value
     */
    public void addHeaderDateParameter(String id, String label, Date value) {
        ReportCell parameter = new ReportCellImpl(new UnmodifiableTuple<String, String>(label, DateUtils.dateToStringDDMMYYYY(value)));
        parameter.setRendererType(TYPE_REPORT_HEADER);
        this.report.getHeader().addParameter(parameter);
    }

    /**
     * Adiciona um novo parâmetro de cabeçalho ao relatório.
     * 
     * @param id id
     * @param label label
     * @param value value
     */
    public void addHeaderTimestampParameter(String id, String label, Timestamp value) {
        ReportCell parameter =
                new ReportCellImpl(new UnmodifiableTuple<String, String>(label, value == null ? "" : DateUtils.dateToStringDDMMYYYY(value)));
        parameter.setRendererType(TYPE_REPORT_HEADER);
        this.report.getHeader().addParameter(parameter);
    }

    /**
     * Adiciona um componente de texto ao relatório.
     * 
     * @param id id
     * @param title title
     * @param body body
     * @return textBox
     */
    public ReportTextBox addTextBox(String id, String title, String body) {
        ReportTextBox textBox = new ReportTextBoxImpl(id, title, body);
        this.report.addElement(textBox);
        return textBox;
    }

    /**
     * Adiciona um texto de rodape das páginas do relatório.
     * 
     * @param text text
     */
    public void setFooterText(String text) {
        this.report.getParameters().put(REPORT_FOOTER_TEXT, text);
    }

    /**
     * @param parametersPerRow parametersPerRow
     */
    public void setHeaderParametersPerRow(int parametersPerRow) {
        this.report.getHeader().setParametersPerRow(parametersPerRow);
    }

    /**
     * Cria o relatório de acordo com os parâmetros que foram passados ao builder.
     * 
     * @return Report
     */
    public Report createReport() {
        Report r = this.report;
        this.report = null;
        return r;
    }

    /**
     * Retorna parâmetros do report.
     * 
     * @return {@link RendererParameters}
     */
    public RendererParameters getReportParameter() {
        return this.report.getParameters();
    }
}
